home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#41 (Feb 89)
/
security code
/
Patrol.p
< prev
next >
Wrap
Text File
|
1988-11-29
|
14KB
|
580 lines
UNIT Patrol;
{-------------------------------------------}
(*
©1988 by Steve Seaquist. All rights reserved.
Used by permission. Use at your own risk.
No warranty is expressed or implied.
This Macintosh virus-detecting program was
originally published and explained in the
February 1989 issue of MacTutor magazine.
Some aspects of its design are important to
security, and it uses some unusual
techniques, so please read the article.
*)
{-------------------------------------------}
INTERFACE
USES
MemTypes,QuickDraw,OSIntf,ToolIntf,
PackIntf,Globals;
PROCEDURE BuildDirname;
PROCEDURE InitPatrols;
PROCEDURE PatrolDirectories
(pOnly1Deep:BOOLEAN);
PROCEDURE PatrolEverything;
PROCEDURE PatrolFiles;
{*******************************************}
IMPLEMENTATION
{$R-}
CONST
kPatsInitd = -12345;
TYPE
TOverlappingPBs =
RECORD
CASE INTEGER OF
0: (fPBRec: HParamBlockRec);
1: (fCPBRec: CInfoPBRec);
END;
VAR
gAAPatImpl: SignedByte;
gAppDirId: LONGINT;
gAppVRefNum: INTEGER;
gInitdFlag: LONGINT;
gOnly1Deep: BOOLEAN;
gOrigWDRefNum: INTEGER;
gPBs: TOverlappingPBs;
gSFLst: SFTypeList;
gSysDirId: LONGINT;
gSysVRefNum: INTEGER;
gWDPBRec: WDPBRec;
gZZPatImpl: SignedByte;
{-------------------------------------------}
PROCEDURE BuildDirname;
VAR
sErr: OSErr;
sLen: INTEGER;
sName: Str255;
sPBs: TOverlappingPBs;
BEGIN
IF gOption[eTrace] THEN
Trace('BuildDirname');
WITH sPBs,fPBRec,fCPBRec DO
BEGIN
sPBs := gPBs;
ioNamePtr := @sName;
ioVRefNum := gCurrWDRefNum;
gCurrDirname := '';
IF gHFS THEN
BEGIN
ioFDirIndex := -1;
ioDrParID := 0;
REPEAT
ioDrDirId := ioDrParID;
sErr := PBGetCatInfo(@fCPBRec,FALSE);
IF (sErr <> NoErr) THEN
EXIT(BuildDirname);
sLen :=
LENGTH(sName)+1+LENGTH(gCurrDirname);
IF (sLen <= 255) THEN
gCurrDirname :=
CONCAT(sName,':',gCurrDirname);
UNTIL ioDrDirId = 2;
END
ELSE
BEGIN
sErr := PBGetVol(@fPBRec,FALSE);
IF (sErr = NoErr) THEN
gCurrDirname := CONCAT(sName,':');
END;
END;
END;
{-------------------------------------------}
PROCEDURE CallProcessFile;
BEGIN
gActiveSelf :=
(gCurrVRefNum = gAppVRefNum) AND
(gCurrDirId = gAppDirId) AND
(gCurrFilename = StringPtr(kCurApName)^);
gActiveSys :=
(gCurrVRefNum = gSysVRefNum) AND
(gCurrDirId = gSysDirId) AND
(gCurrFilename = StringPtr(kSysResName)^);
gCurrFileDeleted := FALSE;
ProcessFile;
END;
{-------------------------------------------}
PROCEDURE FloatWDDeeper
(pDrDirId: LONGINT);
BEGIN
IF gOption[eTrace] THEN
TraceNbr('Begin FloatWDDeeper, WD = ',
ORD4(gCurrWDRefNum));
WITH gPBs,fCPBRec DO
BEGIN
IF NOT((pDrDirId=0) OR (pDrDirId=2)) THEN
BEGIN
gWDPBRec.ioVRefNum := gCurrWDRefNum;
gWDPBRec.ioWDDirId := 0;
gError := PBCloseWD(@gWDPBRec,FALSE);
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t close WD');
EXIT(FloatWDDeeper);
END;
END;
gWDPBRec.ioVRefNum := gCurrVRefNum;
gWDPBRec.ioWDDirId := ioDrDirId;
gError := PBOpenWD(@gWDPBRec,FALSE);
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t open subdir WD');
EXIT(FloatWDDeeper);
END;
gCurrWDRefNum := gWDPBRec.ioVRefNum;
END;
IF gOption[eTrace] THEN
TraceNbr('End FloatWDDeeper, WD = ',
ORD4(gCurrWDRefNum));
END;
{-------------------------------------------}
PROCEDURE FloatWDShallower
(pDrDirId: LONGINT);
BEGIN
IF gOption[eTrace] THEN
TraceNbr('Begin FloatWDShallower, WD = ',
ORD4(gCurrWDRefNum));
WITH gPBs,fCPBRec DO
BEGIN
gError := PBCloseWD(@gWDPBRec,FALSE);
gWDPBRec.ioVRefNum := gCurrWDRefNum;
gWDPBRec.ioWDDirId := 0;
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t close subdir WD');
EXIT(FloatWDShallower);
END;
IF (pDrDirId = 0)
OR (pDrDirId = 2) THEN
gCurrWDRefNum := gOrigWDRefNum
ELSE
BEGIN
gWDPBRec.ioVRefNum := gCurrVRefNum;
gWDPBRec.ioWDDirId := pDrDirId;
gError := PBOpenWD(@gWDPBRec,FALSE);
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t reopen WD');
EXIT(FloatWDShallower);
END;
gCurrWDRefNum := gWDPBRec.ioVRefNum;
END;
END;
IF gOption[eTrace] THEN
TraceNbr('End FloatWDShallower, WD = ',
ORD4(gCurrWDRefNum));
END;
{-------------------------------------------}
PROCEDURE GetActualDirId
(pDrDirId: LONGINT);
BEGIN
WITH gPBs,fCPBRec DO
BEGIN
ioDrDirId := pDrDirId;
ioFDirIndex := -1;
ioVRefNum := gOrigWDRefNum;
gError := PBGetCatInfo(@fCPBRec,FALSE);
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t GetActualDirId');
EXIT(GetActualDirId);
END;
gCurrDInfo := ioDrUsrWds;
gCurrDirId := ioDrDirId;
IF gOption[eTrace] THEN
TraceNbr('ActualDirID = ',gCurrDirId);
END;
END;
{-------------------------------------------}
PROCEDURE InitPatrols;
BEGIN
IF gOption[eTrace] THEN
Trace('InitPatrols');
WITH gPBs,fPBRec,fCPBRec DO
BEGIN
ZeroOutRange(@gAAPatImpl,@gZZPatImpl);
gHFS := TWordPtr(kSFCBLen)^ > 0;
ioNamePtr := @gCurrFilename;
IF gHFS THEN
BEGIN
gError := GetVRefNum
(TWordPtr(kSysMap)^,gSysVRefNum);
IF (gError <> NoErr) THEN
ErrorOSErr('Couldn’t get act sys vol');
ioVRefNum := gSysVRefNum;
gError := PBHGetVInfo(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
ErrorOSErr('Couldn’t get act sys dir');
IF (fPBRec.ioVFndrInfo[1] = 0) THEN
ErrorOSErr('Boot vol not Blessed');
gSysDirId := ioVFndrInfo[1];
gError := PBHGetVol(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
ErrorOSErr('Couldn’t get own DirId');
gAppDirId := ioDirId;
gCurrDirId := ioDirId;
gCurrWDRefNum := ioVRefNum;
ioVolIndex := 0;
gError := PBHGetVInfo(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
ErrorOSErr('Couldn’t get own VInfo');
gAppVRefNum := ioVRefNum;
END
ELSE
BEGIN
gSysVRefNum := TWordPtr(kBootDrive)^;
gError := PBGetVol(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
ErrorOSErr('Couldn’t get own Vol');
gAppVRefNum := ioVRefNum;
gCurrWDRefNum := ioVRefNum;
gAppDirId := 2;
gSysDirId := 2;
gCurrDirId := 2;
END;
BuildDirname;
gCurrFilename := StringPtr(kCurApName)^;
ioFDirIndex := 0;
ioDirId := 0;
ioVRefNum := gCurrWDRefNum;
gError := PBGetFInfo(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
ErrorOSErr('Couldn’t get own FInfo');
gCurrFInfo := ioFlFndrInfo;
gActiveSelf := TRUE;
gActiveSys := FALSE;
gWDPBRec.ioWDProcID := $50617472; {'Patr'}
gInitdFlag := kPatsInitd;
END;
END;
{-------------------------------------------}
PROCEDURE PatrolDir
(pDrDirId: LONGINT);
VAR
sIndex: INTEGER;
BEGIN
IF gOption[eTrace] THEN
TraceNbr('PatrolDir ',pDrDirId);
WITH gPBs,fCPBRec DO
BEGIN
IF (gInitdFlag <> kPatsInitd) THEN
BEGIN { shouldn't happen }
ErrorOSErr('InitPatrols not done');
EXIT(PatrolDir);
END;
IF gHFS THEN
BEGIN
gCurrDirId := pDrDirId;
GetActualDirId(pDrDirId);
IF (gError <> NoErr) THEN
EXIT(PatrolDir);
END
ELSE
gCurrDirId := 2;
BuildDirname;
DirectoryBegins;
sIndex := 1;
REPEAT
gCurrIndex := sIndex;
ioFDirIndex := sIndex;
ioDrDirId := 0;
ioVRefNum := gCurrWDRefNum;
gError := PBGetFInfo(@fPBRec,FALSE);
IF (gError = NoErr) THEN
BEGIN
gCurrFInfo := ioFlFndrInfo;
CallProcessFile;
END
ELSE IF (gError <> fnfErr) THEN
BEGIN
ErrorOSErr('Couldn’t get a file');
EXIT(PatrolDir);
END;
IF NOT(gCurrFileDeleted) THEN
INC(sIndex);
UNTIL (gError <> NoErr) OR gAbortPatrol;
IF gAbortPatrol THEN
EXIT(PatrolDir);
IF (gError <> fnfErr) THEN
BEGIN
ErrorOSErr('Error at end of files');
EXIT(PatrolDir);
END;
gError := NoErr;
IF gHFS AND NOT(gOnly1Deep) THEN
BEGIN
sIndex := 1;
REPEAT
gCurrIndex := sIndex;
ioFDirIndex := sIndex;
ioDrDirId := 0;
ioVRefNum := gCurrWDRefNum;
gError := PBGetCatInfo(@fCPBRec,FALSE);
IF (gError = NoErr) THEN
BEGIN
IF BTst(ORD4(ioFlAttrib),4) THEN
BEGIN
FloatWDDeeper (pDrDirId);
IF (gError <> NoErr) THEN
EXIT(PatrolDir);
PatrolDir(ioDrDirId);
IF (gError <> NoErr)
AND (pDrDirId <> 0)
AND (pDrDirId <> 2) THEN
EXIT(PatrolDir);
FloatWDShallower(pDrDirId);
IF (gError <> NoErr) THEN
EXIT(PatrolDir);
END;
END
ELSE IF (gError <> fnfErr) THEN
BEGIN
ErrorOSErr('Couldn’t get a dir');
EXIT(PatrolDir);
END;
INC(sIndex);
UNTIL (gError <> NoErr) OR gAbortPatrol;
IF gAbortPatrol THEN
EXIT(PatrolDir);
IF (gError <> fnfErr) THEN
BEGIN
ErrorOSErr('Error at end of subdirs');
EXIT(PatrolDir);
END;
gError := NoErr;
gCurrDirId := pDrDirId;
GetActualDirId(pDrDirId);
IF (gError <> NoErr) THEN
EXIT(PatrolDir);
BuildDirname;
END;
DirectoryEnds;
END;
END;
{-------------------------------------------}
PROCEDURE PatrolDirectories
(pOnly1Deep:BOOLEAN);
BEGIN
IF gOption[eTrace] THEN
Trace('PatrolDirectories ');
WITH gPBs,fPBRec,fCPBRec,gSFRep DO
BEGIN
IF (gInitdFlag <> kPatsInitd) THEN
BEGIN { shouldn't happen }
ErrorOSErr('InitPatrols not done');
EXIT(PatrolDirectories);
END;
gOnly1Deep := pOnly1Deep;
SFGetFile
(gSFGetPt,'',NIL,-1,gSFLst,NIL,gSFRep);
WHILE good DO
BEGIN
IF gHFS THEN
BEGIN
ioVRefNum := gSFRep.vRefNum;
ioVolIndex := 0;
gError := PBHGetVInfo(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t get own VInfo');
LEAVE;
END;
gCurrVRefNum := ioVRefNum;
END
ELSE
gCurrVRefNum := vRefNum;
gCurrWDRefNum := vRefNum;
gOrigWDRefNum := vRefNum;
PatrolBegins;
PatrolDir(0);
PatrolEnds;
IF (gError <> NoErr) THEN
LEAVE;
SFGetFile
(gSFGetPt,'',NIL,-1,gSFLst,NIL,gSFRep);
END;
gError := NoErr;
END;
END;
{-------------------------------------------}
PROCEDURE PatrolEverything;
VAR
sIndex: INTEGER;
BEGIN
IF gOption[eTrace] THEN
Trace('PatrolEverything ');
WITH gPBs,fPBRec,fCPBRec DO
BEGIN
IF (gInitdFlag <> kPatsInitd) THEN
BEGIN { shouldn't happen }
ErrorOSErr('InitPatrols not done');
EXIT(PatrolEverything);
END;
gOnly1Deep := FALSE;
PatrolBegins;
ioVRefNum := 0;
sIndex := 1;
REPEAT
gCurrIndex := sIndex;
ioVolIndex := sIndex;
gError := PBGetVInfo(@fPBRec,FALSE);
IF (gError = NoErr) THEN
BEGIN
gCurrVRefNum := ioVRefNum;
gCurrWDRefNum := ioVRefNum;
gOrigWDRefNum := ioVRefNum;
PatrolDir(2);
IF (gError <> NoErr) THEN
EXIT(PatrolEverything);
INC(sIndex);
END
ELSE IF (gError <> nsvErr) THEN
BEGIN
ErrorOSErr('Couldn’t get a volume');
EXIT(PatrolEverything);
END;
UNTIL gError <> NoErr;
IF (gError <> nsvErr) THEN
BEGIN
ErrorOSErr('Error at end of volumes');
EXIT(PatrolEverything);
END;
gError := NoErr;
PatrolEnds;
END;
END;
{-------------------------------------------}
PROCEDURE PatrolFiles;
VAR
sPrevDirId: LONGINT;
sPrevVRefNum: INTEGER;
sPrevWDRefNum:INTEGER;
{------------------------}
PROCEDURE CallPrevDirEnd;
VAR
sTempDirId: LONGINT;
sTempVRefNum: INTEGER;
sTempWDRefNum:INTEGER;
BEGIN
IF (sPrevWDRefNum <> 0) THEN
BEGIN
sTempDirId := gCurrDirId;
sTempVRefNum := gCurrVRefNum;
sTempWDRefNum := gCurrWDRefNum;
gCurrDirId := sPrevDirId;
gCurrVRefNum := sPrevVRefNum;
gCurrWDRefNum := sPrevWDRefNum;
DirectoryEnds;
gCurrDirId := sTempDirId;
gCurrVRefNum := sTempVRefNum;
gCurrWDRefNum := sTempWDRefNum;
END;
END;
{------------------------}
BEGIN
IF gOption[eTrace] THEN
Trace('PatrolFiles ');
WITH gPBs,fPBRec,fCPBRec,gSFRep DO
BEGIN
IF (gInitdFlag <> kPatsInitd) THEN
BEGIN { shouldn't happen }
ErrorOSErr('InitPatrols not done');
EXIT(PatrolFiles);
END;
PatrolBegins;
sPrevWDRefNum := 0;
SFGetFile
(gSFGetPt,'',NIL,-1,gSFLst,NIL,gSFRep);
WHILE good DO
BEGIN
IF gHFS THEN
BEGIN
ioVRefNum := gSFRep.vRefNum;
ioDrDirId := 0;
ioFDirIndex := -1;
gError := PBGetCatInfo(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t get DirId');
LEAVE;
END;
gCurrDirId := ioDrDirId;
ioVolIndex := 0;
gError := PBHGetVInfo(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t get VInfo');
LEAVE;
END;
gCurrVRefNum := ioVRefNum;
END
ELSE
BEGIN
gCurrDirId := 2;
gCurrVRefNum := vRefNum;
END;
gCurrFilename := fName;
gCurrIndex := 0;
gCurrWDRefNum := vRefNum;
IF (sPrevWDRefNum <> gCurrWDRefNum) THEN
BEGIN
CallPrevDirEnd;
BuildDirname;
DirectoryBegins;
sPrevDirId := gCurrDirId;
sPrevVRefNum := gCurrVRefNum;
sPrevWDRefNum := gCurrWDRefNum;
END;
ioDrDirId := gCurrDirId;
ioFDirIndex := gCurrIndex;
ioVRefNum := gCurrWDRefNum;
gError := PBGetFInfo(@fPBRec,FALSE);
IF (gError <> NoErr) THEN
BEGIN
ErrorOSErr('Couldn’t get FInfo');
LEAVE;
END;
gCurrFInfo := ioFlFndrInfo;
CallProcessFile;
IF gAbortPatrol THEN
LEAVE;
SFGetFile
(gSFGetPt,'',NIL,-1,gSFLst,NIL,gSFRep);
END;
gError := NoErr;
CallPrevDirEnd;
PatrolEnds;
END;
END;
{*******************************************}
END.